package com.symaster.gameengine.e2d;

import com.symaster.gameengine.core.Component;
import com.symaster.gameengine.core.FboComponent;
import com.symaster.gameengine.core.FrameCall;
import com.symaster.gameengine.util.SceneUtil;
import org.lwjgl.opengl.GL11;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Comparator;
import java.util.List;

/**
 * 场景
 *
 * @author yinmiao
 * @version 2023/11/15
 */
public class Scene extends FboComponent {

    private static final Logger log = LoggerFactory.getLogger(Scene.class);
    private float aspectRatio;
    private long window;

    public float getAspectRatio() {
        return aspectRatio;
    }

    public void setAspectRatio(float aspectRatio) {
        this.aspectRatio = aspectRatio;
    }

    public long getWindow() {
        return window;
    }

    public void setWindow(long window) {
        this.window = window;
    }

    @Override
    public void repaint2Fbo() {
        // 更新帧事件
        this.frameCallUpdate();
        // 递归获取场景中的所有Camera
        List<Camera> cameras = getComponents(Camera.class, true);
        // 相机层排序
        List<Camera> cameraSort = cameras.stream()
                .sorted(Comparator.comparingInt(Component::getLayer))
                .toList();

        // 绑定到 FBO
        this.bindFbo();
        this.clear();

        // 循环绘制相机
        for (Camera camera : cameraSort) {

            // 设置相机宽高比
            camera.setAspectRatio(aspectRatio);
            // 设置相机渲染的场景
            camera.setRenderScene(this);
            // 相机绘制
            camera.repaint2Fbo();
            // 绑定到 FBO
            this.bindFbo();
            // 相机绘制区域
            GL11.glViewport(
                    camera.getPaintX(),
                    camera.getPaintY(),
                    SceneUtil.autoMax(camera.getPaintWidth(), getFboWidth()),
                    SceneUtil.autoMax(camera.getPaintHeight(), getFboHeight())
            );
            // 绘制相机FBO
            camera.renderTextureToScreen();
        }
    }

    private void frameCallUpdate() {
        // 递归获取场景中的所有帧前更新事件
        List<FrameCall> frameCalls = getComponentByInterface(FrameCall.class, true);
        // 帧前更新
        for (FrameCall frameCall : frameCalls) {
            frameCall.update(window);
        }
    }

    /**
     * 加载当前组件需要的资源
     */
    public void resourceLoad() {
        // 加载当前场景中所有组件需要的资源
        SceneUtil.resourceLoad(this);
    }
}
